// Render
// (c) jimon game studio

#ifndef JEH_IRENDER
#define JEH_IRENDER

#include "Config_Engine.h"
#include "jeMaterial.h"
#include "IHardwareBufferArray.h"
#include "jeRenderOperation.h"
#include "jeStl.h"
#include "IRenderContext.h"
#include "IRenderTarget.h"
#include "IRenderTargetTexture.h"
#include "ITexture.h"
#include "je3dTypes.h"
#include "IShaderGlobalVariable.h"

namespace je
{
	namespace video
	{
		//! Graphics Driver Type
		enum GraphicsDriverType
		{
			//! OpenGL
			GDT_OPENGL
		};

		//! Render Matrix Type
		enum RenderMatrixType
		{
			//! Projection Matrix
			RMT_PROJECTION,

			//! Model Matrix
			RMT_MODEL,

			//! View Matrix
			RMT_VIEW,

			//! Texture Matrix
			RMT_TEXTURE
		};

		//! Texture Creation Flags
		enum TextureCreationFlags
		{
			//! Default Texture
			TCF_DEFAULT = 0,

			//! Create MipMap levels
			TCF_MIPMAPED = 1,

			//! Filtered Texture
			TCF_FILTERED = 2,

			//! Compress Texture
			TCF_COMPRESS_DXT3 = 4,

			//! Compress Texture
			TCF_COMPRESS_DXT5 = 8
		};

		//! Depth Mode
		enum DepthMode
		{
			//! Never
			DM_NEVER,

			//! Less
			DM_LESS,

			//! Less or equal
			DM_LEQUAL,

			//! Equal
			DM_EQUAL,

			//! Greater
			DM_GREATER,

			//! Not equal
			DM_NOTEQUAL,

			//! Greater or equal
			DM_GEQUAL,

			//! Always
			DM_ALWAYS
		};

		//! Pre Render Operation Callback
		class IPreRenderOperationCallback:public je::jeUnknown
		{
		public:
			//! Constructor
			IPreRenderOperationCallback()
			{
			}

			//! Destructor
			virtual ~IPreRenderOperationCallback()
			{
			}

			//! On Render Operation
			virtual void OnRenderOperation(RenderOperationType Type,jeRenderOperation * Data)
			{
			}
		};

		//! Render
		class IRender:public je::jeUnknown
		{
		public:
			//! Destructor
			virtual ~IRender()
			{
			}

			// -------------------------- Texture --------------------------

			//! Create Texture
			virtual ITexture * CreateTexture(IImage * Image,TextureFormat Format = TF_RGBA8,s32 Flags = TCF_DEFAULT) = 0;

			//! Create Texture
			virtual ITexture * CreateTexture(const jeVector2di & Size,TextureFormat Format = TF_RGBA8,s32 Flags = TCF_DEFAULT) = 0;

			//! Create Texture Multisample
			virtual ITexture * CreateTextureMultisample(const jeVector2di & Size,TextureFormat Format = TF_RGBA8,s32 Samples = 0) = 0;

			//! Create Render Buffer Texture
			//! You can use it only with RenderTargetTexture
			virtual ITexture * CreateRenderBufferTexture(const jeVector2di & Size,TextureFormat Format = TF_RGBA8,s32 Samples = 0) = 0;

			// -------------------------- Shader Material --------------------------

			//! Create Shader Material
			virtual IShaderMaterial * CreateShaderMaterial(const jeStringc & Source) = 0;

			//! Set Shader Material Define (if PasteCode = true, simply add "Define" string to shader source, if false add #define DefineName Define)
			virtual void SetShaderMaterialDefine(const jeStringc & DefineName,const jeStringc & Define,u1 PasteCode = false) = 0;

			//! UnSet Shader Material Define
			virtual void UnSetShaderMaterialDefine(const jeStringc & DefineName) = 0;

			//! Get Shader Material Define
			virtual jeStringc GetShaderMaterialDefine(const jeStringc & DefineName) = 0;

			//! Recompile Shaders
			virtual void RecompileShaders() = 0;
			
			//! Get Default Shader Material
			virtual IShaderMaterial * GetDefaultShaderMaterial() = 0;

			//! Set Shaders Global Technique
			virtual void SetShadersGlobalTechnique(u8 Technique = 0) = 0;

			//! Get Shaders Global Technique
			virtual u8 GetShadersGlobalTechnique() = 0;

			//! Get Global Shader Variable
			virtual IShaderGlobalVariable * GetGlobalShaderVariable(const jeStringc & Name,u1 CreateNewInstance = false) = 0;

			// -------------------------- Hardware Buffer --------------------------

			//! Create Hardware Buffer
			virtual IHardwareBuffer * CreateHardwareBuffer(Graphics3dDataType Type) = 0;

			//! Create Hardware Buffer Array
			virtual IHardwareBufferArray * CreateHardwareBufferArray() = 0;

			// -------------------------- Context --------------------------

			//! Create Render Context
			virtual IRenderContext * CreateContext() = 0;

			//! Set Render Context
			virtual void SetContext(IRenderContext * Context) = 0;

			//! Get Render Context
			virtual IRenderContext * GetContext() = 0;

			// -------------------------- Render Target --------------------------

			//! Create Texture Render Traget
			virtual IRenderTargetTexture * CreateTextureRenderTarget() = 0;

			//! Set Render Target
			virtual void SetTarget(IRenderTarget * RenderTarget) = 0;

			//! Get Render Target
			virtual IRenderTarget * GetTarget() = 0;

			// -------------------------- Render Control --------------------------

			//! Begin
			virtual void Begin() = 0;

			//! End
			virtual void End() = 0;

			// -------------------------- Screen Control --------------------------

			//! Clear Screen
			virtual void ClearScreen(const jeColorARGB32f & Color) = 0;

			//! Clear Depth
			virtual void ClearDepth() = 0;

			//! Clear Screen
			virtual void ClearScreen()
			{
				ClearScreen(jeColorARGB32f(0,0,0,0));
			}

			// -------------------------- Viewport Control --------------------------

			//! Set Viewport
			virtual void SetViewport(u1 UseContextSize = true,s32 X = 0,s32 Y = 0,s32 Width = 0,s32 Height = 0) = 0;

			//! Get Viewport Position
			virtual jeVector2di GetViewportPosition() = 0;

			//! Get Viewport Size
			virtual jeVector2di GetViewportSize() = 0;

			// -------------------------- Render Operation --------------------------

			//! Render Operation
			virtual void RenderOperation(RenderOperationType Type,jeRenderOperation * Data = NULL) = 0;

			//! Set Pre Render Operation Callback
			virtual void SetPreRenderOperationCallback(IPreRenderOperationCallback * Callback) = 0;

			//! Get Pre Render Operation Callback
			virtual IPreRenderOperationCallback * GetPreRenderOperationCallback() = 0;

			//! Set Force Render Operation Setup
			virtual void SetForceRenderOperationSetup(u1 Enabled) = 0;

			//! Get Force Render Operation Setup
			virtual u1 GetForceRenderOperationSetup() = 0;

			// -------------------------- Matrix --------------------------

			//! Set Matrix
			virtual void SetMatrix(const jeMatrix4f & Matrix,RenderMatrixType Type) = 0;

			//! Get Matrix
			virtual const jeMatrix4f & GetMatrix(RenderMatrixType Type) = 0;

			// -------------------------- Materials --------------------------

			//! Set Material
			virtual void SetMaterial(jeMaterial * Material) = 0;

			//! Get Material
			virtual jeMaterial * GetMaterial() = 0;

			//! Get Default Material
			virtual jeMaterial * GetDefaultMaterial() = 0;

			//! Get Currently Used Shader Material
			virtual IShaderMaterial * GetCurrentlyUsedShaderMaterial() = 0;

			//! Enable Ignoring Shader Material Change
			virtual void EnableIgnoringShaderMaterialChange(u1 Enable) = 0;

			//! Set Global Texture
			virtual void SetGlobalTexture(ITexture * Texture,s32 TextureLayer) = 0;

			//! Set Global Material Type
			virtual void SetGlobalMaterialType(u1 Enable,MaterialType Type = MT_SOLID) = 0;

			// -------------------------- Depth Pass Mode --------------------------

			//! Set Depth Mode
			virtual void SetDepthMode(DepthMode Mode = DM_LESS) = 0;

			//! Get Depth Mode
			virtual DepthMode GetDepthMode() = 0;

			// -------------------------- Service Functions --------------------------

			//! Copy Framebuffer to texture
			virtual void CopyFrameBufferToTexture(ITexture * Texture,jeVector2di Start,jeVector2di WidthHeight) = 0;

			//! Get Rendered Triangles Count
			virtual u32 GetRenderedTrianglesCount() = 0;
		};

		//! Create Render
		JE_ENGINE_FUNCTION_API video::IRender * JE_ENGINE_FUNCTION_CALL CreateRender(video::GraphicsDriverType Type);
	}
}

#endif
